import React, { useEffect, useState } from 'react';
import PropTypes from 'prop-types';

import ViewerMain from '../ViewerMain';
import ErrorBoundaryDialog from '../ErrorBoundaryDialog';
import PanelTabs from '../PanelTabs';
import Toolbar from '../Toolbar';
import { MODULE_TYPES } from '@ohif/core';
import { extensionManager, servicesManager } from '../../App.js';
import { Layout } from 'antd';
import ReactResizeDetector from 'react-resize-detector/build/withPolyfill';
import cloneDeep from 'lodash.clonedeep';

import './Viewer.styl';
import { useSelector } from 'react-redux';

const Viewer = props => {
  const { studies, studyInstanceUIDs, isStudyLoaded } = props;

  useEffect(() => {
    if (isStudyLoaded) {
      const { MeasurementService } = servicesManager.services;
      MeasurementService.measurementApi.retrieveMeasurements();
    }
  }, [isStudyLoaded]);

  const sidePanels = useSelector(state => {
    return state.preferences.sidePanels;
  });

  const panelExtensions = extensionManager.modules[MODULE_TYPES.PANEL];
  const updatedPanelMap = {};
  panelExtensions.forEach(panelExt => {
    panelExt.module.components.forEach(comp => {
      updatedPanelMap[comp.id] = comp;
    });
  });

  const [panelMap, setPanelMap] = useState(updatedPanelMap);
  const [panelPosMap, setPanelPosMap] = useState(cloneDeep(sidePanels));

  useEffect(() => {
    if (sidePanels.auto) return;
    setPanelPosMap(cloneDeep(sidePanels));
  }, [sidePanels]);

  const onResize = (width, height) => {
    const posMap = { ...panelPosMap };
    let changed = false;
    Object.keys(panelMap).forEach(panelId => {
      if (!sidePanels[panelId] || !posMap[panelId]) return;
      if (sidePanels[panelId].pos !== 'auto') return;

      if (width > height) {
        posMap[panelId].pos = 'left';
      } else {
        posMap[panelId].pos = 'bottom';
      }

      changed = true;
    });

    if (changed) {
      setPanelPosMap(posMap);
    }
  }

  const getSidebarSize = (panels, key = 'width') => {
    let size = 0;
    panels.forEach(p => {
      if (size < p[key]) {
        size = p[key];
      }
    });
    return size;
  }

  let auto = !!Object.keys(sidePanels).find(id => sidePanels[id].pos === 'auto' && sidePanels[id].show);
  let leftPanels = [], topPanels = [], rightPanels = [], bottomPanels = [];
  Object.keys(panelPosMap).forEach(panelId => {
    if (!panelPosMap[panelId].show) return;

    switch(panelPosMap[panelId].pos) {
      case 'left':
        leftPanels.push(panelMap[panelId]);
        break;
      case 'top':
        topPanels.push(panelMap[panelId]);
        break;
      case 'right':
        rightPanels.push(panelMap[panelId]);
        break;
      case 'bottom':
        bottomPanels.push(panelMap[panelId]);
        break;
    }
  });

  return (
    <>
      { /* Toolbar */}
      <Toolbar />

      <Layout className="outer-layout">
        {auto && (
          <ReactResizeDetector
            refreshMode="debounce"
            refreshRate={200}
            onResize={onResize}
          />
        )}
        {leftPanels.length > 0 && (
          <Layout.Sider className="left-sider" width={getSidebarSize(leftPanels)}>
            {/* LEFT */}
            <PanelTabs
              panels={leftPanels}
              studies={studies}
              position="left"
            />
          </Layout.Sider>
        )}
        <Layout className="inner-layout" style={{ overflow: 'hidden' }}>
          {topPanels.length > 0 && (
            <Layout.Header style={{ height: `${getSidebarSize(topPanels, 'height')}px`, padding: 0 }}>
              {/* TOP */}
              <PanelTabs
                panels={topPanels}
                studies={studies}
                position="top"
              />
            </Layout.Header>
          )}
          <Layout.Content className="layout-content">
            {/* MAIN */}
            <ErrorBoundaryDialog context="ViewerMain">
              <ViewerMain
                studies={studies}
                isStudyLoaded={isStudyLoaded}
              />
            </ErrorBoundaryDialog>
          </Layout.Content>
          {bottomPanels.length > 0 && (
            <Layout.Footer style={{ height: `${getSidebarSize(bottomPanels, 'height')}px`, padding: 0 }}>
              { /* BOTTOM */}
              <PanelTabs
                panels={bottomPanels}
                studies={studies}
                position="bottom"
              />
            </Layout.Footer>
          )}
        </Layout>
        {rightPanels.length > 0 && (
          <Layout.Sider className="right-sider" width={getSidebarSize(rightPanels)}>
            {/* RIGHT */}
            <PanelTabs
              panels={rightPanels}
              studies={studies}
              position="right"
            />
          </Layout.Sider>
        )}
      </Layout>
    </>
  );
}

Viewer.propTypes = {
  studies: PropTypes.arrayOf(
    PropTypes.shape({
      StudyInstanceUID: PropTypes.string.isRequired,
      StudyDate: PropTypes.string,
      PatientID: PropTypes.string,
      displaySets: PropTypes.arrayOf(
        PropTypes.shape({
          displaySetInstanceUID: PropTypes.string.isRequired,
          SeriesDescription: PropTypes.string,
          SeriesNumber: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
          InstanceNumber: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
          numImageFrames: PropTypes.number,
          Modality: PropTypes.string,
          images: PropTypes.arrayOf(
            PropTypes.shape({
              getImageId: PropTypes.func.isRequired,
            })
          ),
        })
      ),
    })
  ),
  studyInstanceUIDs: PropTypes.array,
  isStudyLoaded: PropTypes.bool,
  sidePanels: PropTypes.object,
};

export default Viewer;
